package xfuzzy.xfghl.mutation;

import java.util.Random;

import xfuzzy.xfghl.codification.ChromosomeFixer;
import xfuzzy.xfghl.codification.DoubleChromosome;
import xfuzzy.xfghl.model.XfghlConfig;

/**
 * Clase que representa la mutacion en un individuo
 * @author Alberto David Fernandez Fernandez
 * */

public class Mutation {
	
	/**
	 * Variable para la generacion de numeros aleatorios
	 * */
	private Random random;
	
	/**
	 * Constructor de la clase
	 * @param seed Semilla del generador de numeros aleatorios
	 * */
	public Mutation(long seed)  {
		
		this.random = new Random(seed);
	}
	
	// la mutacion consiste en:
	// 1. intercambiar dos variables de posicion
	// 2. intercambiar dos posiciones en la estructura
	
	/**
	 * Metodo que realiza la mutacion sobre dos individuos
	 * @param c1 Individuo a mutar
	 * @param c2 Individuo a mutar
	 * @param config Configuracion de la herramienta Xfghl
	 * */
	
	public void mutar(DoubleChromosome c1, DoubleChromosome c2, XfghlConfig config)  {
		
		if (this.random.nextDouble() < config.getMutationProbability())  {
			this.mutarVariables(c1, config);
			this.mutarEstructura(c1, config);
			ChromosomeFixer.reparar(c1, config);
		}
		if (this.random.nextDouble() < config.getMutationProbability())  {
			this.mutarVariables(c2, config);
			this.mutarEstructura(c2, config);
			ChromosomeFixer.reparar(c2, config);
		}
	}
	
	/**
	 * Metodo que realiza la mutacion sobre las variables del individuo
	 * @param c1 Individuo a mutar
	 * @param config Configuracion de la herramienta Xfghl
	 * */
	
	private void mutarVariables(DoubleChromosome c1, XfghlConfig config)  {
		
		// Mutacion de las variables
		int auxiliar = -1;
		int [] variables = c1.getVariables();
		int indice1 = this.random.nextInt(c1.getNumVariables());
		int indice2 = this.random.nextInt(c1.getNumVariables());
		while (indice1 == indice2)
			indice2 = this.random.nextInt(c1.getNumVariables());
		
		auxiliar = variables[indice1];
		variables[indice1] = variables[indice2];
		variables[indice2] = auxiliar;
		c1.setEvaluated(false);
	}
	
	/**
	 * Metodo que realiza la mutacion sobre la estructura del individuo
	 * @param c1 Individuo a mutar
	 * @param config Configuracion de la herramienta Xfghl
	 * */
	
	private void mutarEstructura(DoubleChromosome c1, XfghlConfig config)  {
		
		char auxiliar = ' ';
		char [] estructura = c1.getEstructura();
		int indice1 = this.random.nextInt(estructura.length);
		int indice2 = this.random.nextInt(estructura.length);
		while (indice1 == indice2)
			indice2 = this.random.nextInt(estructura.length);
		
		auxiliar = estructura[indice1];
		estructura[indice1] = estructura[indice2];
		estructura[indice2] = auxiliar;
		c1.setEvaluated(false);
	}
}
